#ifndef QUERY_PLANNER_H
#define QUERY_PLANNER_H

#include "../../include/gudb.h"
#include "../parser/sql_parser.h"
#include "../stats/statistics_collector.h"
#include "../config/config_manager.h"
#include <stdint.h>
#include <stdbool.h>

// Plan node types
typedef enum {
    PLAN_INVALID = 0,
    PLAN_SCAN,                  // Table scan
    PLAN_INDEX_SCAN,            // Index scan
    PLAN_FILTER,                // Filter (WHERE clause)
    PLAN_PROJECT,               // Projection (SELECT list)
    PLAN_JOIN,                  // Join operations
    PLAN_AGGREGATE,             // Aggregation (GROUP BY)
    PLAN_SORT,                  // ORDER BY
    PLAN_LIMIT,                 // LIMIT/OFFSET
    PLAN_INSERT,                // INSERT operation
    PLAN_UPDATE,                // UPDATE operation
    PLAN_DELETE,                // DELETE operation
    PLAN_UNION,                 // UNION operations
    PLAN_SUBQUERY               // Subquery
} plan_node_type_t;

// Join types
typedef enum {
    JOIN_INNER = 0,
    JOIN_LEFT_OUTER,
    JOIN_RIGHT_OUTER,
    JOIN_FULL_OUTER,
    JOIN_CROSS,
    JOIN_SEMI,
    JOIN_ANTI
} join_type_t;

// Statistics for cost estimation
typedef struct {
    uint64_t row_count;         // Estimated number of rows
    uint64_t page_count;        // Number of pages
    double selectivity;         // Selectivity factor (0.0 - 1.0)
    double avg_row_size;        // Average row size in bytes
    bool has_index;             // Whether index is available
    uint32_t distinct_values;   // Number of distinct values
} plan_stats_t;

// Cost estimation structure
typedef struct {
    double cpu_cost;            // CPU processing cost
    double io_cost;             // I/O cost
    double memory_cost;         // Memory usage cost
    double total_cost;          // Total estimated cost
    uint64_t cardinality;       // Estimated output cardinality
} plan_cost_t;

// Forward declarations
typedef struct plan_node plan_node_t;
typedef struct optimizer_context optimizer_context_t;
typedef struct rule rule_t;
typedef struct memo_group memo_group_t;

// Plan node structure
struct plan_node {
    plan_node_type_t type;
    uint32_t node_id;
    
    // Node-specific data
    union {
        struct {                // PLAN_SCAN
            char* table_name;
            char* alias;
            expression_t* filter;
            plan_stats_t stats;
        } scan;
        
        struct {                // PLAN_INDEX_SCAN
            char* table_name;
            char* index_name;
            expression_t* index_condition;
            expression_t* filter;
            bool is_unique;
            plan_stats_t stats;
        } index_scan;
        
        struct {                // PLAN_FILTER
            expression_t* condition;
            plan_node_t* child;
        } filter;
        
        struct {                // PLAN_PROJECT
            expression_t** expressions;
            char** column_names;
            uint32_t expr_count;
            plan_node_t* child;
        } project;
        
        struct {                // PLAN_JOIN
            join_type_t join_type;
            expression_t* condition;
            plan_node_t* left;
            plan_node_t* right;
            plan_stats_t stats;
        } join;
        
        struct {                // PLAN_AGGREGATE
            expression_t** group_by;
            expression_t** aggregates;
            uint32_t group_count;
            uint32_t agg_count;
            plan_node_t* child;
        } aggregate;
        
        struct {                // PLAN_SORT
            expression_t** sort_keys;
            bool* ascending;
            uint32_t key_count;
            plan_node_t* child;
        } sort;
        
        struct {                // PLAN_LIMIT
            uint64_t limit;
            uint64_t offset;
            plan_node_t* child;
        } limit;
        
        struct {                // PLAN_INSERT
            char* table_name;
            char** column_names;
            expression_t** values;
            uint32_t column_count;
            uint32_t value_count;
        } insert;
        
        struct {                // PLAN_UPDATE
            char* table_name;
            expression_t** assignments;
            expression_t* condition;
            uint32_t assignment_count;
        } update;
        
        struct {                // PLAN_DELETE
            char* table_name;
            expression_t* condition;
        } delete;
    } data;
    
    // Cost information
    plan_cost_t cost;
    
    // Optimization metadata
    memo_group_t* group;        // Memo group this plan belongs to
    uint32_t optimization_level;
    
    // Child nodes (for tree structure)
    plan_node_t** children;
    uint32_t child_count;
    
    // Next node in the same memo group
    struct plan_node* next;
};

// Memo group for Cascades optimizer
struct memo_group {
    uint32_t group_id;
    plan_node_t* expressions;   // List of equivalent expressions
    plan_cost_t best_cost;      // Best cost found so far
    plan_node_t* best_plan;     // Best plan found so far
    bool explored;              // Whether group has been explored
    bool optimized;             // Whether group has been optimized
    
    // Properties
    uint64_t cardinality;       // Estimated cardinality
    bool has_interesting_order; // Whether group has interesting sort order
    
    struct memo_group* next;    // Hash table collision chain
};

// Transformation rule
struct rule {
    char* name;
    bool (*condition)(plan_node_t* node);
    plan_node_t* (*transform)(plan_node_t* node, optimizer_context_t* ctx);
    double priority;
    bool is_implementation;     // True for implementation rules, false for transformation
};

// Optimizer context
struct optimizer_context {
    // Configuration
    uint32_t max_iterations;
    double cost_threshold;
    bool enable_join_reordering;
    bool enable_predicate_pushdown;
    bool enable_index_selection;
    
    // Statistics
    uint32_t rules_applied;
    uint32_t groups_explored;
    uint32_t plans_considered;
    
    // Memo table
    memo_group_t** memo_table;
    uint32_t memo_table_size;
    uint32_t memo_group_count;
    uint32_t next_group_id;
    
    // Rules
    rule_t* transformation_rules;
    rule_t* implementation_rules;
    uint32_t transformation_rule_count;
    uint32_t implementation_rule_count;
    
    // Table statistics (for cost estimation)
    plan_stats_t* table_stats;
    uint32_t table_count;
    
    // Integrated systems
    statistics_collector_t* stats_collector;  // 统计信息收集系统
    config_manager_t* config_manager;         // 配置管理系统
    
    // Cost model parameters (from config)
    double cpu_cost_factor;
    double io_cost_factor;
    double memory_cost_factor;
    double index_selectivity_boost;
    uint32_t hash_join_threshold;
};

// Query planner structure
typedef struct {
    optimizer_context_t* optimizer;
    
    // Current planning session
    statement_t* current_stmt;
    plan_node_t* current_plan;
    
    // Statistics
    uint64_t plans_generated;
    uint64_t optimization_time_us;
    
    // Configuration
    bool enable_optimization;
    uint32_t optimization_level;  // 0=minimal, 1=basic, 2=full
} query_planner_t;

// Query planner API
query_planner_t* planner_create(void);
void planner_destroy(query_planner_t* planner);

// Main planning functions
plan_node_t* planner_create_plan(query_planner_t* planner, statement_t* stmt);
plan_node_t* planner_optimize_plan(query_planner_t* planner, plan_node_t* plan);

// Plan creation functions
plan_node_t* planner_create_scan_plan(const char* table_name, expression_t* filter);
plan_node_t* planner_create_index_scan_plan(const char* table_name, const char* index_name, 
                                           expression_t* condition);
plan_node_t* planner_create_filter_plan(expression_t* condition, plan_node_t* child);
plan_node_t* planner_create_project_plan(expression_t** expressions, char** column_names, 
                                        uint32_t expr_count, plan_node_t* child);
plan_node_t* planner_create_join_plan(join_type_t join_type, expression_t* condition,
                                     plan_node_t* left, plan_node_t* right);
plan_node_t* planner_create_sort_plan(expression_t** sort_keys, bool* ascending,
                                     uint32_t key_count, plan_node_t* child);
plan_node_t* planner_create_limit_plan(uint64_t limit, uint64_t offset, plan_node_t* child);

// Optimizer context functions
optimizer_context_t* optimizer_create_context(void);
void optimizer_destroy_context(optimizer_context_t* ctx);
int optimizer_add_transformation_rule(optimizer_context_t* ctx, rule_t* rule);
int optimizer_add_implementation_rule(optimizer_context_t* ctx, rule_t* rule);

// Memo management
memo_group_t* memo_create_group(optimizer_context_t* ctx);
int memo_add_expression(optimizer_context_t* ctx, memo_group_t* group, plan_node_t* expr);
memo_group_t* memo_find_group(optimizer_context_t* ctx, uint32_t group_id);

// Cost estimation
plan_cost_t estimate_plan_cost(plan_node_t* plan, optimizer_context_t* ctx);
double estimate_selectivity(expression_t* condition, plan_stats_t* stats);
uint64_t estimate_cardinality(plan_node_t* plan, optimizer_context_t* ctx);

// Cascades optimization algorithm
int cascades_optimize_group(optimizer_context_t* ctx, memo_group_t* group);
int cascades_explore_group(optimizer_context_t* ctx, memo_group_t* group);
int cascades_apply_rules(optimizer_context_t* ctx, memo_group_t* group);

// Built-in transformation rules
bool rule_predicate_pushdown_condition(plan_node_t* node);
plan_node_t* rule_predicate_pushdown_transform(plan_node_t* node, optimizer_context_t* ctx);

bool rule_join_commutativity_condition(plan_node_t* node);
plan_node_t* rule_join_commutativity_transform(plan_node_t* node, optimizer_context_t* ctx);

bool rule_join_associativity_condition(plan_node_t* node);
plan_node_t* rule_join_associativity_transform(plan_node_t* node, optimizer_context_t* ctx);

bool rule_projection_pushdown_condition(plan_node_t* node);
plan_node_t* rule_projection_pushdown_transform(plan_node_t* node, optimizer_context_t* ctx);

// Built-in implementation rules
bool rule_scan_to_index_scan_condition(plan_node_t* node);
plan_node_t* rule_scan_to_index_scan_transform(plan_node_t* node, optimizer_context_t* ctx);

bool rule_join_to_nested_loop_condition(plan_node_t* node);
plan_node_t* rule_join_to_nested_loop_transform(plan_node_t* node, optimizer_context_t* ctx);

bool rule_join_to_hash_join_condition(plan_node_t* node);
plan_node_t* rule_join_to_hash_join_transform(plan_node_t* node, optimizer_context_t* ctx);

// Utility functions
void plan_print_tree(plan_node_t* plan, int indent);
void plan_destroy(plan_node_t* plan);
plan_node_t* plan_clone(plan_node_t* plan);
bool plan_equals(plan_node_t* a, plan_node_t* b);

// Statistics functions
int planner_load_table_stats(query_planner_t* planner, const char* table_name);
int planner_update_table_stats(query_planner_t* planner, const char* table_name, 
                              const plan_stats_t* stats);

// Enhanced cost estimation with real statistics
plan_cost_t estimate_plan_cost_with_stats(plan_node_t* plan, optimizer_context_t* ctx);
double estimate_selectivity_with_stats(expression_t* condition, uint32_t table_id, 
                                      uint32_t column_id, optimizer_context_t* ctx);
uint64_t estimate_join_cardinality(plan_node_t* left, plan_node_t* right, 
                                  expression_t* condition, optimizer_context_t* ctx);

// Configuration integration
int optimizer_load_config_params(optimizer_context_t* ctx);
int optimizer_update_cost_factors(optimizer_context_t* ctx);

// Configuration functions
int planner_set_optimization_level(query_planner_t* planner, uint32_t level);
int planner_enable_rule(query_planner_t* planner, const char* rule_name, bool enabled);

// Debugging functions
void planner_print_memo(optimizer_context_t* ctx);
void planner_print_stats(query_planner_t* planner);

// String conversion functions
const char* plan_node_type_to_string(plan_node_type_t type);
const char* join_type_to_string(join_type_t type);

#endif // QUERY_PLANNER_H